#include "copyright.h"

#include "syscall.h"
#include "RegularCustomer.h"

void finishedAgent(){

	/*if(GetMonitor(ManagerFinishedName, ManagerFinishedNameLength, 0) == 1){
		Exit(1);
	}*/

}


int regularCustomerInitialize(){

	int custNum;
	int groupNum;
	
	AcquireLock(regularCustomerIndexLockName,regularCustomerIndexLockNameLength);
		
		custNum = GetMonitor(nextRegularCustomerName, nextRegularCustomerNameLength,0 );
		groupNum = custNum/MAX_GROUPS;
		
		if(custNum % 4 == 0){
			custNum++;
		}
		
		SetMonitor(nextRegularCustomerName, nextRegularCustomerNameLength, custNum + 1, 0);

		SetMonitor(numCustomersName, numCustomersNameLength, GetMonitor(numCustomersName, numCustomersNameLength, 0) + 1, 0);
		/*SetMonitor(custCounterName, custCounterNameLength, GetMonitor(custCounterName, custCounterNameLength, 0) + 1, 0);*/

		/*Printing("nextCustomerIndex = %i\n", ConsoleOutput, GetMonitor(nextRegularCustomerName, nextRegularCustomerNameLength,0), 0);*/

	ReleaseLock(regularCustomerIndexLockName,regularCustomerIndexLockNameLength);

	SetMonitor(customerNumberName, customerNumberNameLength, custNum, custNum);
	SetMonitor(customerGroupNumberName, customerGroupNumberNameLength, groupNum, custNum/4);
	SetMonitor(customerWantsPopcornName, customerWantsPopcornNameLength, -1, custNum);
	SetMonitor(customerWantsSodaName, customerWantsSodaNameLength, -1, custNum);
	SetMonitor(customerNeedsBathroomName, customerNeedsBathroomNameLength, -1, custNum);
	SetMonitor(customerIsHeadCustomerName, customerIsHeadCustomerNameLength, -1, custNum);
	SetMonitor(customerSeatNumberName, customerSeatNumberNameLength, -1, custNum);
	SetMonitor(customerHasPopcornName, customerHasPopcornNameLength, -1, custNum);
	SetMonitor(customerHasSodaName, customerHasSodaNameLength, -1, custNum);
	


	return custNum;

}

void regularCustomer(){

	int myIndex;
	int tempRegCustomer;
	int i;
	int tmp;
	int printGroup;
	
	myIndex = regularCustomerInitialize();
	printGroup = myIndex/4;

	/*BEGIN: RegularCustomer - HeadCustomer Interaction, Deciding on Food*/

	AcquireLock(headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);

	/*STEP 1: RegularCustomer waits for Head customer to broadcast (ask them if they want food)*/
	Printing("Customer %i of group %i is waiting for the group to form.\n",ConsoleOutput, myIndex, printGroup);
	Printing("Customer %i of group %i is waiting for the HeadCustomer.\n", ConsoleOutput, myIndex, printGroup);
	Wait(regularCustomerConditionVariableName[printGroup], regularCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	finishedAgent();
	Printing("Customer %i of group %i has been told by the HeadCustomer to proceed.\n", ConsoleOutput, myIndex, printGroup);
  
	/*STEP 2: The customer is asked by the head, andx the regular customer decides if they want food.*/
	SetMonitor(customerWantsPopcornName, customerWantsPopcornNameLength, (Random()%4 > 0) ? 1 : 0, myIndex);
	/*customerWantsPopcorn[myIndex] = (Random()%4 > 0) ? 1 : 0;*/
	SetMonitor(customerWantsSodaName, customerWantsSodaNameLength, (Random()%4 > 0) ? 1 : 0, myIndex);
	/*customerWantsSoda[myIndex] = (Random()%4 > 0) ? 1 : 0;*/
	
	Printing("Customer %i in group %i \0", ConsoleOutput, myIndex, printGroup);
	Printing("wants %i popcorn and %i soda.\n" , ConsoleOutput, GetMonitor(customerWantsPopcornName, customerWantsPopcornNameLength, myIndex),GetMonitor(customerWantsSodaName, customerWantsSodaNameLength, myIndex));
	
	Printing("Customer %i in Group %i has \0", ConsoleOutput, myIndex, printGroup);
	Printing("%i popcorn and %i soda request from a group member\n", ConsoleOutput, GetMonitor(customerWantsPopcornName, customerWantsPopcornNameLength, myIndex), GetMonitor(customerWantsSodaName, customerWantsSodaNameLength, myIndex));
	

	Signal(headCustomerConditionVariableName[printGroup], headCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	Wait(regularCustomerConditionVariableName[printGroup], regularCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	finishedAgent();

	/*END: RegularCustomer - HeadCustomer Interaction, Deciding on Food*/
	
	/*BEGIN: RegularCustomer - HeadCustomer Interaction, Getting line from head customer*/
	
	Printing("Customer %i in group %i is sitting in a theater room seat.\n", ConsoleOutput, myIndex, printGroup);

	/*printf("(RCust%i, group%i: Im in seat %i.)\n", myIndex, customerGroupNumber[myIndex], customerSeatNumber[myIndex]);*/

	Signal(headCustomerConditionVariableName[printGroup], headCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	Wait(regularCustomerConditionVariableName[printGroup], regularCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	finishedAgent();

	Printing("Customer %i in group %i is getting out of a theater room seat.\n", ConsoleOutput, myIndex, printGroup);

	
	/*END: RegularCustomer - HeadCustomer Interaction, Getting line from head customer*/

	/*BEGIN: Bathroom deciding*/
	
	SetMonitor(customerNeedsBathroomName, customerNeedsBathroomNameLength, (Random()%4 > 0) ? 0 : 1, myIndex);
	/*customerNeedsBathroom[myIndex] = (Random()%4 > 0) ? 0 : 1;*/
	
	if(GetMonitor(customerNeedsBathroomName, customerNeedsBathroomNameLength, myIndex)){
		Printing("Customer %i in Group %i is going to the bathroom.\n", ConsoleOutput, myIndex, printGroup);
	}
	
	Signal(headCustomerConditionVariableName[printGroup], headCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	Wait(regularCustomerConditionVariableName[printGroup], regularCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	finishedAgent();

	if(GetMonitor(customerNeedsBathroomName, customerNeedsBathroomNameLength, myIndex) == 0){

		AcquireLock(bathroomLockName[printGroup], bathroomLockNameLength[printGroup]);

		Signal(headCustomerConditionVariableName[printGroup], headCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);

	 /*Wait(regularCustomerConditionVariable[customerGroupNumber[myIndex]], headCustomerLock[customerGroupNumber[myIndex]]);*/

		
		/*ReleaseLock(headCustomerLock[customerGroupNumber[myIndex]]);*/
		/*Wait(bathroomLobbyConditionVariable[customerGroupNumber[myIndex]], bathroomLock[customerGroupNumber[myIndex]]);*/

		
		
		ReleaseLock(bathroomLockName[printGroup], bathroomLockNameLength[printGroup]);
		
	}
	else{
		
		
	
		AcquireLock(bathroomLockName[printGroup], bathroomLockNameLength[printGroup]);

		SetMonitor(groupBathroomSizeName, groupBathroomSizeNameLength, GetMonitor(groupBathroomSizeName, groupBathroomSizeNameLength, printGroup) - 1, printGroup);
		/*groupBathroomSize[printGroup]--;	*/
		
		/*printf("(RCust%i: Done going to the bathroom  There are still %i people were waiting for.)\n", myIndex,groupBathroomSize[customerGroupNumber[myIndex]]);*/

		ReleaseLock(bathroomLockName[printGroup], bathroomLockNameLength[printGroup]);
		
		if(GetMonitor(groupBathroomSizeName, groupBathroomSizeNameLength,printGroup) == 0){
			Broadcast(bathroomLobbyConditionVariableName[printGroup], bathroomLobbyConditionVariableNameLength[printGroup], bathroomLockName[printGroup], bathroomLockNameLength[printGroup]);
		}

		Signal(headCustomerConditionVariableName[printGroup], headCustomerConditionVariableNameLength[printGroup], headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
			
		Printing("Customer %i in Group %i is leaving the bathroom.\n", ConsoleOutput, myIndex, printGroup);
	
	}
	
	/*Wait(regularCustomerConditionVariable[customerGroupNumber[myIndex]], headCustomerLock[customerGroupNumber[myIndex]]);*/

	Printing("Customer %i in Group %i has left the movie theater.\n", ConsoleOutput, myIndex, printGroup);
	/*END: Bathroom deciding*/
	
	ReleaseLock(headCustomerLockName[printGroup], headCustomerLockNameLength[printGroup]);
	
}


int main(){

	regularCustomer();

Exit(1);
}
